package initialization;

import instrumentation.Condition;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import operations.Operation;
import operations.ValuesGenerator;
import util.DebugConfig;
import util.GAConfig;
import util.Log;
import util.Randomness;
import ga.GAInfo;
import ga.Individual;
import mdr.RecommendGenerator;
import model.TestClusterBuilder;
import model.StatementKind;
public class MDRPopulationInitializer implements PopulationInitializer{ 
	protected GAInfo gaInfo;
	private static final int POPULATION_SIZE    = GAConfig.PopulationSize;
	private static final int TEST_SIZE_GOAL = GAConfig.TestCaseSize;
	@Override
	public Individual[] createPopulation() {
		TestClusterBuilder TestCluster=gaInfo.getTestCluster();
	//	this.printConfigurations(configurations);
		
		Individual[] population = new Individual[POPULATION_SIZE];
		//Generate random population
		for(int individual = 0; individual < POPULATION_SIZE; individual++) {
			// Create initial Objects available for testing
			 List<Operation> initialConstructors= Operation.dependenceGenerateInitialConstructors(TestCluster);
			 
		//	List<StatementKind>  configurations =this.getConfiguration();

			List<Operation> ops = new LinkedList<Operation>();
			 ops.addAll(Operation.recGenerateOperation(TestCluster,TEST_SIZE_GOAL,gaInfo));
			
			population[individual] = new Individual(initialConstructors,ops);
		}		
		return population;
	}
	@Override
	public void printPopulation() {
		if (!DebugConfig.printPopulation)
			return;
		Log.log("++++++++++++++++++++++++++++++++++++++++");
		Log.log("\t\t Generation " + gaInfo.getGeneration());
		for (Individual individual : this.gaInfo.getPopulation()) {
			Log.log("------------------------------------------");
			Log.log(individual.toString() + " fitness: "
					+ individual.getFitness() + " size:" + individual.getSize());
		}
	}
	
	@Override
	public void setExtraInfo(GAInfo gaInfo) {
		this.gaInfo = gaInfo;
	}
	public List<StatementKind> getConfiguration(){
		RecommendGenerator recommendGenerator=gaInfo.getRecommendGenerator();
		TreeMap<Integer,Condition> sorted_map = new TreeMap<Integer,Condition>(recommendGenerator.getCondition());
		List<Integer> branches=new LinkedList<Integer>(sorted_map.keySet());
		int trgtBranch=ValuesGenerator.getRandomIntBetween(0, branches.size()-1);
//		System.out.println("getConfiguration trgetBranch:"+ branches.get(trgtBranch));
		Map<Class<?>,  List<StatementKind>> relatedStatement=recommendGenerator.getBranchRelStatementList().get(branches.get(trgtBranch));
		if(relatedStatement==null||relatedStatement.size()==0)
			return null;
		else{
			List<StatementKind> selectedStatementKind=relatedStatement.get(relatedStatement.keySet().toArray()[Randomness.nextRandomInt(relatedStatement.size())]);
//			System.out.println("getConfiguration selected StatementKind:"+ selectedStatementKind);
			
			int numberOmittedMethods=ValuesGenerator.getRandomIntBetween(0, selectedStatementKind.size()-1);
//			System.out.println("getConfiguration number Omitted Methods:"+ numberOmittedMethods);
			List<StatementKind> methodList = new LinkedList<StatementKind>();
			methodList.addAll(selectedStatementKind);

			for (int i = 1; i <= numberOmittedMethods; i++) {
				int randMethod = Randomness.nextRandomInt(methodList
						.size());
				StatementKind st = methodList.get(randMethod);

				methodList.removeAll(Collections.singleton(st));
			}
//			System.out.println("getConfiguration configuration:"+ methodList);
			return methodList;

		}
			
		
		
	}
}
